package service

import (
	"gobase/app/model"
	"gobase/util"
	"strconv"
	"strings"

	"github.com/casbin/casbin"

	"github.com/Sirupsen/logrus"
	"github.com/gin-gonic/gin"
	"github.com/pkg/errors"
	"github.com/xormplus/xorm"
)

type RoleResourceService struct {
	dao *xorm.Engine
	log *logrus.Logger
	ce  *casbin.Enforcer
}

//初始化方法
func NewRoleResourceService(c *gin.Context) *RoleResourceService {
	return &RoleResourceService{dao: util.GetDb(c), log: util.GetLog(c), ce: util.GetCasbin(c)}
}

//获取角色资源
func (srv *RoleResourceService) GetRoleResourceList(roleid int) []map[string]string {
	sql := "SELECT r.id, r.parent_id AS pid, r.title AS name, ( CASE WHEN r.category = 3 THEN 0 ELSE 1 END ) AS isParent, (CASE WHEN rr.id THEN 1 ELSE 0 END) AS checked FROM resource AS r LEFT JOIN role_resource AS rr ON rr.resourceid = r.id AND rr.roleid = ? ORDER BY r.parent_id asc, r.sortnum asc"
	sliceStrList, err := srv.dao.SQL(sql, roleid).QueryString()
	if err != nil {
		srv.log.Errorf("RoleResourceService->GetRoleResourceList 获取角色资源：%s", err)
	}
	return sliceStrList
}

//关联权限
//roleid int 角色ID
//resourceIds []string 所选功能
//写入 role_resource表
func (srv *RoleResourceService) AuthorizeFunc(roleid int, resourceIds []string) error {
	session := srv.dao.NewSession()
	defer session.Close()
	roleidStr := strconv.Itoa(roleid)

	if err := session.Begin(); err != nil {
		return errors.Wrap(err, "开启事务失败!")
	}

	//删除已有的关联
	_, err := session.Sql("delete from role_resource where roleid=?", roleid).Execute()
	if err != nil {
		return errors.Wrap(err, "删除角色已关联权限失败!")
	}

	//保存新的关联
	if len(resourceIds) > 0 {
		var insertSQL = "insert into role_resource(roleid,resourceid) values"
		var excuteSQL = ""

		//执行插入方法
		var insertFunc = func(sql1 string) error {
			sql1 = sql1[0 : len(sql1)-1]
			_, _, err := session.Sqls(sql1).Execute()
			if err != nil {
				session.Rollback()
				srv.log.Errorf("RoleResourceService->authorizeFunc %s", err)
				return err
			}
			return nil
		}

		for i, v := range resourceIds {
			excuteSQL += "('" + roleidStr + "','" + v + "'),"
			//100条执行一次
			if i == 99 {
				err = insertFunc(insertSQL + excuteSQL)
				if err != nil {
					return errors.Wrap(err, "更新角色权限失败!")
				}
				excuteSQL = ""
			}
		}

		if len(excuteSQL) > 0 {
			ierr := insertFunc(insertSQL + excuteSQL)
			if ierr != nil {
				return errors.Wrap(err, "更新角色权限失败!")
			}
		}
	}

	err = session.Commit()
	if err != nil {
		return errors.Wrap(err, "提交事务失败!")
	}

	//casbin 同步策略
	srv.dao.SQL("delete from casbin_rule where p_type='p' where v0=?", roleidStr).Execute()
	srv.ce.LoadPolicy()
	if len(resourceIds) > 0 {
		ids := strings.Join(resourceIds, ",")
		var resList []*model.Resource
		srv.dao.SQL("select * from resource where id in (" + ids + ") and url <>'#' ").Find(&resList)
		util.AddFuncsForRole(srv.ce, roleid, resList)
	}

	return nil
}
